//============================================================================
// Name        : Merceria.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <fstream>
#include "ArchivoDeBloques/ArchivoDeBloques.h"
#include "Hash/Tabla.h"
#include "Hash/Bucket.h"
#include "Hash/Hash.h"
#include "Identificadores/Instancia.h"
#include "IndiceArbolBMas/ElementoInterno.h"
#include "IndiceArbolBMas/ElementoHoja.h"
#include "IndiceArbolBMas/NodoInterno.h"
#include "IndiceArbolBMas/NodoHoja.h"
#include "IndiceArbolBMas/Indice.h"
#include "IndiceArbolBMas/ResultadoBuscar.h"
#include "Identificadores/NodosId.h"
#include "ABMsEntidades/ABMTintura.h"
#include "ABMsEntidades/ABMFormador.h"
#include "ABMsEntidades/ABMMaterial.h"
#include "ABMsEntidades/ABMBretel.h"
#include "ABMsEntidades/ABMCopa.h"
#include "ABMsEntidades/ABMFamilia.h"
#include "ABMsEntidades/ABMCorpino.h"
#include "ABMsEntidades/ABMVentas.h"
#include "Reportes/Reporte.h"
#include "Menu/Menu.h"
#include <cstring>
#include <iterator>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

int verEntidades() {
	ArchivoDeBloques archivo("./src/dat/entidades.dat");

	for (int i = 0; i < archivo.cantBloques; i++) {
		cout << archivo.leerBloque(i)->bufferBloque << endl;
	}

}

int altaArbolTest() {
	int tamBloqueArbol = 95;

	Indice indice("altaTree", tamBloqueArbol);

	//Ejemplo: ventas:3$14$15/11/2014$336$CONSUMIDOR FINAL
	//La clave es el primer registro!

	//Prueba overflow nodo hoja

	ElementoHoja elemento1(50, "14;25/11/2014;350;PRIMERO");
	ElementoHoja elemento2(100, "15;26/11/2014;400;SEGUNDO");
	ElementoHoja elemento3(150, "16;27/11/2014;450;TERCERO");
	ElementoHoja elemento4(500, "17;28/11/2014;500;CUARTO");
	ElementoHoja elemento5(151, "18;29/11/2014;600;Q");
	ElementoHoja elemento6(601, "19;30/11/2014;650;SEXTO");

	indice.alta(elemento1);
	indice.alta(elemento2);
	indice.alta(elemento3);
	indice.alta(elemento4);
	indice.alta(elemento5);
	indice.alta(elemento6);

	//Prueba overflow nodo indice

	ElementoHoja elemento7(602, "19;30/11/2014;650;SI");
	ElementoHoja elemento8(603, "19;30/11/2014;650;OC");
	ElementoHoja elemento9(604, "19;30/11/2014;650;NU");
	ElementoHoja elemento10(605, "19;30/11/2014;650;DI");
	ElementoHoja elemento11(606, "19;30/11/2014;650;ON");
	ElementoHoja elemento12(607, "19;30/11/2014;650;DOC");
	ElementoHoja elemento13(608, "19;30/11/2014;650;TREC");
	ElementoHoja elemento14(609, "19;30/11/2014;650;CATO");
	ElementoHoja elemento15(610, "19;30/11/2014;650;QUIN");
	ElementoHoja elemento16(611, "19;30/11/2014;650;DIC");
	ElementoHoja elemento17(612, "19;30/11/2014;650;DIC");
	ElementoHoja elemento18(613, "19;30/11/2014;650;DIC");
	ElementoHoja elemento19(614, "19;30/11/2014;650;DIC");
	ElementoHoja elemento20(615, "19;30/11/2014;650;VE");
	ElementoHoja elemento21(616, "19;30/11/2014;650;VE");

	indice.alta(elemento7);
	indice.alta(elemento8);
	indice.alta(elemento9);
	indice.alta(elemento10);
	indice.alta(elemento11);
	indice.alta(elemento12);
	indice.alta(elemento13);
	indice.alta(elemento14);
	indice.alta(elemento15);
	indice.alta(elemento16);
	indice.alta(elemento17);
	indice.alta(elemento18);
	indice.alta(elemento19);
	indice.alta(elemento20);
	indice.alta(elemento21);

	for (int i = 0; i < indice.archivoBloques->cantBloques; i++) {
		cout << indice.archivoBloques->leerBloque(i)->bufferBloque << endl;
	}

	cout << "" << endl;
	//Prueba baja comun
	indice.baja(615);

	for (int i = 0; i < indice.archivoBloques->cantBloques; i++) {
		cout << indice.archivoBloques->leerBloque(i)->bufferBloque << endl;
	}

	cout << endl << "Prueba de recorrer arbol ordenado: " << endl;
	vector<ElementoHoja> vectorElementos = indice.recorreOrdenado();
	for (unsigned int i = 0; i < vectorElementos.size(); i++) {
		cout << "Clave: " << vectorElementos.at(i).clave << " Valor: "
				<< vectorElementos.at(i).valor << endl;
	}
}

int numeroNodoTest() {
	NodosId ids;
	ids.inicializarIdNodo(0);
	cout << ids.obtenerIdNodo() << endl;
	ids.incrementarIdNodo();
	cout << ids.obtenerIdNodo() << endl;
	ids.incrementarIdNodo();
	cout << ids.obtenerIdNodo() << endl;
	ids.inicializarIdNodo(100);
	cout << ids.obtenerIdNodo() << endl;
}

int modificarArbolTest() {
	Indice indice("treeFile");
	ElementoHoja elemento1(150, "ABCD");
	ElementoHoja elemento2(800, "XYZ");

	indice.modificar(elemento1);
	indice.modificar(elemento2);

	cout << indice.archivoBloques->leerBloque(0)->bufferBloque << endl;
	cout << indice.archivoBloques->leerBloque(1)->bufferBloque << endl;
	cout << indice.archivoBloques->leerBloque(2)->bufferBloque << endl;
	cout << indice.archivoBloques->leerBloque(3)->bufferBloque << endl;

	//Algunas pruebas de alta
	/*ElementoHoja elemento3(8, "EE");
	 ElementoHoja elemento4(611, "ZZ");
	 ElementoHoja elemento5(9, "GG");
	 ElementoHoja elemento6(610, "YY");
	 indice.alta(elemento3);
	 indice.alta(elemento4);
	 indice.alta(elemento5);
	 indice.alta(elemento6);*/

}

int buscarArbolTest() {
	Indice indice("treeFile");

	cout << "La clave 100: " << indice.buscar(100).numeroDeNodo << endl;
	cout << "Su padre es: " << indice.buscar(100).numeroDeNodoPadre << endl;
	cout << "La clave 150: " << indice.buscar(150).numeroDeNodo << endl;
	cout << "Su padre es: " << indice.buscar(150).numeroDeNodoPadre << endl;
	cout << "La clave 200: " << indice.buscar(200).numeroDeNodo << endl;
	cout << "Su padre es: " << indice.buscar(200).numeroDeNodoPadre << endl;
	cout << "La clave 500: " << indice.buscar(500).numeroDeNodo << endl;
	cout << "Su padre es: " << indice.buscar(500).numeroDeNodoPadre << endl;
	cout << "La clave 800: " << indice.buscar(800).numeroDeNodo << endl;
	cout << "Su padre es: " << indice.buscar(800).numeroDeNodoPadre << endl;

	//NO ESTAN:
	ResultadoBuscar res1 = indice.buscar(25);
	ResultadoBuscar res2 = indice.buscar(250);
	ResultadoBuscar res3 = indice.buscar(900);

	if (!res1.encontrado) {
		cout << "La clave 25 deberia estar en: " << res1.numeroDeNodo << endl;
	}
	if (!res2.encontrado) {
		cout << "La clave 250 deberia estar en: " << res2.numeroDeNodo << endl;
	}
	if (!res3.encontrado) {
		cout << "La clave 900 deberia estar en: " << res3.numeroDeNodo << endl;
	}
	/*
	 const int DIM = 6;
	 int array[DIM] = { 33, 10, 77, 14, 2, 58 };
	 std::vector<int> myVector(array, array + DIM);
	 indice.nodosLibres = myVector;
	 indice.guardarNodosLibres("nodosLibresTest");
	 indice.nodosLibres= {};
	 indice.cargarNodosLibres("nodosLibresTest");

	 for (int i = 0; i < indice.nodosLibres.size(); i++) {
	 cout << indice.nodosLibres.at(i) << endl;
	 }*/

}

int creacionArbolTest() {

	int tamBloqueArbol = 95;
	ElementoInterno interno1(200, 2);
	ElementoInterno interno2(500, 3);

	NodoInterno nodoInterno1;
	nodoInterno1.numeroDeNodo = 0;
	nodoInterno1.nivel = 1;
	nodoInterno1.hijoIzq = 1;
	std::vector<ElementoInterno> elementosNodo1;
	elementosNodo1.push_back(interno1);
	elementosNodo1.push_back(interno2);
	nodoInterno1.elementos = elementosNodo1;
	nodoInterno1.cantidadDeElementos = nodoInterno1.elementos.size();

	ElementoHoja hoja1(100, "valor1");
	ElementoHoja hoja2(150, "valor2");
	ElementoHoja hoja3(200, "valor3");
	ElementoHoja hoja4(500, "valor4");
	ElementoHoja hoja5(800, "valor5");

	NodoHoja nodoHoja1;
	NodoHoja nodoHoja2;
	NodoHoja nodoHoja3;

	nodoHoja1.numeroDeNodo = 1;
	nodoHoja1.nivel = 0;
	nodoHoja1.proximoNodo = 2;
	std::vector<ElementoHoja> elementosHoja1;
	elementosHoja1.push_back(hoja1);
	elementosHoja1.push_back(hoja2);
	nodoHoja1.elementos = elementosHoja1;
	nodoHoja1.cantidadDeElementos = nodoHoja1.elementos.size();

	nodoHoja2.numeroDeNodo = 2;
	nodoHoja2.nivel = 0;
	nodoHoja2.proximoNodo = 3;
	std::vector<ElementoHoja> elementosHoja2;
	elementosHoja2.push_back(hoja3);
	nodoHoja2.elementos = elementosHoja2;
	nodoHoja2.cantidadDeElementos = nodoHoja2.elementos.size();

	nodoHoja3.numeroDeNodo = 3;
	nodoHoja3.nivel = 0;
	nodoHoja3.proximoNodo = -1;
	std::vector<ElementoHoja> elementosHoja3;
	elementosHoja3.push_back(hoja4);
	elementosHoja3.push_back(hoja5);
	nodoHoja3.elementos = elementosHoja3;
	nodoHoja3.cantidadDeElementos = nodoHoja3.elementos.size();

	Indice indice("treeFile", tamBloqueArbol);
	indice.escribirNodoInterno(nodoInterno1);
	indice.escribirNodoHoja(nodoHoja1);
	indice.escribirNodoHoja(nodoHoja2);
	indice.escribirNodoHoja(nodoHoja3);

	cout << "Despues de escribir los nodos en el archivo los leo: " << endl;

	cout << indice.archivoBloques->leerBloque(0)->bufferBloque << endl;
	cout << indice.archivoBloques->leerBloque(1)->bufferBloque << endl;
	cout << indice.archivoBloques->leerBloque(2)->bufferBloque << endl;
	cout << indice.archivoBloques->leerBloque(3)->bufferBloque << endl;

	cout << " Leos los bloques y creo los nodos a partir de los bloques: "
			<< endl;

	NodoInterno nodoInterno;
	NodoHoja nodoHoja;

	Bloque * bloque = indice.leerNodo(0);
	int res = nodoInterno.leerDeBloque(*bloque);
	if (res == -1) {
		cout << "Es una hoja!" << endl;
	} else {
		nodoInterno.guardarEnBloque(tamBloqueArbol);
		cout << nodoInterno.bloque.bufferBloque << endl;
	}

	bloque = indice.leerNodo(1);
	res = nodoHoja.leerDeBloque(*bloque);
	if (res == -1) {
		cout << "Es interno!" << endl;
	} else {
		nodoHoja.guardarEnBloque(tamBloqueArbol);
		cout << nodoHoja.bloque.bufferBloque << endl;
	}

	bloque = indice.leerNodo(2);
	res = nodoHoja.leerDeBloque(*bloque);
	if (res == -1) {
		cout << "Es interno!" << endl;
	} else {
		nodoHoja.guardarEnBloque(tamBloqueArbol);
		cout << nodoHoja.bloque.bufferBloque << endl;
	}

	bloque = indice.leerNodo(3);
	res = nodoHoja.leerDeBloque(*bloque);
	if (res == -1) {
		cout << "Es interno!" << endl;
	} else {
		nodoHoja.guardarEnBloque(tamBloqueArbol);
		cout << nodoHoja.bloque.bufferBloque << endl;
	}

	cout << endl << "Prueba de recorrer arbol ordenado: " << endl;
	vector<ElementoHoja> vectorElementos = indice.recorreOrdenado();
	for (unsigned int i = 0; i < vectorElementos.size(); i++) {
		cout << "Clave: " << vectorElementos.at(i).clave << " Valor: "
				<< vectorElementos.at(i).valor << endl;
	}
}

/*IDEA:
 * Cada entidad va a estar almacenada en un bloque distinto.
 * Cada metadata o atributo de la entidad va a ser un registro dentro del bloque.
 * Opciones de atributos:
 * Entero: E
 * Cadena de caracteres: C
 * Otra entidad: X
 *
 * En el caso de ser cadena en el registro siguiente se especifica la longitud maxima de la misma.
 *
 * Ademas despues del nombre se guarda S o N dependiendo de si el atributo es obligatorio.
 *
 *
 * De esta manera asi queda representada una entidad.
 * NOMBRE$ID_ENTIDAD$(NOMBRE_DE_ATRIBUTO$S_N$TIPO_ATRIBUTO)+
 *
 *
 */
void cargarEntidades() {

	unsigned int tamBloque = 135;
	unsigned int nroBloqueActual = 0;

	ArchivoDeBloques archivoEntidades("entidades.dat", tamBloque);

	//Como las entidades son fijas las creamos como un unico registro

	Bloque bloque1(tamBloque);
	Registro corpino(
			"CORPINO$1$DESCRIPCION$S$C$30$CONTORNO$S$C$5$PRECIO$S$E$MATERIAL$S$X$BRETEL$N$X$COPA$S$X$FAMILIA$S$X$TINTURA$S$X");
	bloque1.agregarRegistro(corpino);
	archivoEntidades.agregarBloquesVacios(1);
	archivoEntidades.escribirBloque(bloque1, nroBloqueActual);

	nroBloqueActual++;

	Bloque bloque2(tamBloque);
	Registro tintura("TINTURA$2$DESCRIPCION$S$C$15$COLOR_ESTAMPA$S$C$5");
	bloque2.agregarRegistro(tintura);
	archivoEntidades.agregarBloquesVacios(1);
	archivoEntidades.escribirBloque(bloque2, nroBloqueActual);

	nroBloqueActual++;

	Bloque bloque3(tamBloque);
	Registro bretel("BRETEL$3$DESCRIPCION$S$C$15");
	bloque3.agregarRegistro(bretel);
	archivoEntidades.agregarBloquesVacios(1);
	archivoEntidades.escribirBloque(bloque3, nroBloqueActual);

	nroBloqueActual++;

	Bloque bloque4(tamBloque);
	Registro material("MATERIAL$4$DESCRIPCION$S$C$15");
	bloque4.agregarRegistro(material);
	archivoEntidades.agregarBloquesVacios(1);
	archivoEntidades.escribirBloque(bloque4, nroBloqueActual);

	nroBloqueActual++;

	Bloque bloque5(tamBloque);
	Registro formador("FORMADOR$5$DESCRIPCION$S$C$15");
	bloque5.agregarRegistro(formador);
	archivoEntidades.agregarBloquesVacios(1);
	archivoEntidades.escribirBloque(bloque5, nroBloqueActual);

	nroBloqueActual++;

	Bloque bloque6(tamBloque);
	Registro copa("COPA$6$FORMADOR$S$X$ARMADO$S$C$5$ARO$S$C$5");
	bloque6.agregarRegistro(copa);
	archivoEntidades.agregarBloquesVacios(1);
	archivoEntidades.escribirBloque(bloque6, nroBloqueActual);

	nroBloqueActual++;

	Bloque bloque7(tamBloque);
	Registro ventas(
			"VENTAS$7$CORPINO$S$X$FECHAVENTA$S$C$10$PRECIO$S$E$CLIENTE$S$C$20");
	bloque7.agregarRegistro(ventas);
	archivoEntidades.agregarBloquesVacios(1);
	archivoEntidades.escribirBloque(bloque7, nroBloqueActual);

	nroBloqueActual++;

	Bloque bloque8(tamBloque);
	Registro familia(
			"FAMILIA$8$DESCRIPCION$S$C$30$FABRICANTE$N$C$30$PRECIO$S$E");
	bloque8.agregarRegistro(familia);
	archivoEntidades.agregarBloquesVacios(1);
	archivoEntidades.escribirBloque(bloque8, nroBloqueActual);

}

void leerEntidades() {
	ArchivoDeBloques archivoEntidades("entidades");

	Bloque* bloqueLeido;
	for (int i = 0; i < archivoEntidades.cantBloques; i++) {
		bloqueLeido = archivoEntidades.leerBloque(i);
		cout << "Bloque " << i << ": " << (*bloqueLeido).bufferBloque << endl;
	}

}

void metadataTest() {
	ArchivoDeBloques archivo("metdataTest", 15);

	int eltamanio = 0;
	ArchivoDeBloques archivoSimple("metdataTest");
	eltamanio = archivoSimple.tamBloque;
	cout << eltamanio << endl;
}

void guardarTabla() {
	const int DIM = 6;
	int array[DIM] = { 33, 10, 77, 14, 2, 58 };
	std::vector<int> myVector(array, array + DIM);
	Tabla tabla(6);
	tabla.setTabla(myVector);
	tabla.guardarTabla("TablaHash");

}

void cargarTabla() {
	Tabla tabla(6);
	tabla.cargarTabla("TablaHash");

	cout << tabla.getTabla().size() << endl;
	cout << tabla.getTabla().at(0) << endl;
	cout << tabla.getTabla().at(1) << endl;
	cout << tabla.getTabla().at(2) << endl;
	cout << tabla.getTabla().at(3) << endl;
	cout << tabla.getTabla().at(4) << endl;
	cout << tabla.getTabla().at(5) << endl;
}

void contarRegistrosTest() {

	Bloque bloque1(30);
	Registro reguno("PRIMERO");
	Registro regdos("SEGUNDO");
	bloque1.agregarRegistro(reguno);
	bloque1.agregarRegistro(regdos);
	bloque1.agregarRegistro(reguno);
	cout << bloque1.cantidadRegistros() << endl;
}

void obtenerRegistroTest() {
	Bloque bloque1(30);
	Registro reguno("PRIMERO");
	Registro regdos("SEGUNDO");
	Registro regtres("tercero");
	bloque1.agregarRegistro(reguno);
	bloque1.agregarRegistro(regdos);
	bloque1.agregarRegistro(regtres);
	cout << bloque1.obtenerRegistro(1)->buffer << endl;
	cout << bloque1.obtenerRegistro(2)->buffer << endl;
	cout << bloque1.obtenerRegistro(3)->buffer << endl;

}

int escribirRegistroTest() {
	ArchivoDeBloques archivo("prueba", 15);
	Registro reg("HOLA");
	archivo.escribirRegistro(reg, 0);
}

int crearArchivoTest() {

	//ArchivoDeBloques archivo("prueba", 1, 3);
	ArchivoDeBloques archivo("prueba", 15);

}

int agregarBloquesVaciosTest() {
	ArchivoDeBloques archivo("prueba", 0, 3);
	archivo.agregarBloquesVacios(3);
}

int crearBloques() {
	Registro reguno("PRIMERO");
	Registro regdos("SEGUN");
	Bloque bloque1(15);

	bloque1.agregarRegistro(reguno);
	bloque1.agregarRegistro(regdos);

	bloque1.completarConCeros();
	cout << bloque1.bufferBloque << endl;

	Bloque bloque2(15);
	Registro regter("TER");
	bloque2.agregarRegistro(regter);
	bloque2.completarConCeros();
	cout << bloque2.bufferBloque << endl;

}

int agregarRegistroTest() {
	int res;
	Registro reguno("PRIMERO");
	Registro regdos("SEG");
	Registro regter("TEM");

	Bloque bloque(15);
	cout << bloque.bufferBloque << endl;

	res = bloque.agregarRegistro(reguno);
	if (res != -1) {
		cout << bloque.bufferBloque << endl;
	} else {
		cout << "no hay lugar" << endl;
	}
	cout << bloque.obtenerBytesLibres() << endl;

	res = bloque.agregarRegistro(regdos);
	if (res != -1) {
		cout << bloque.bufferBloque << endl;
	} else {
		cout << "no hay lugar" << endl;
	}
	cout << bloque.obtenerBytesLibres() << endl;

	res = bloque.agregarRegistro(regter);
	if (res != -1) {
		cout << bloque.bufferBloque << endl;

	} else {
		cout << "no hay lugar" << endl;
	}
	cout << bloque.obtenerBytesLibres() << endl;

}

/*********************************************************
 * lore
 *********************************************************/

void crearKeyTest() {
	Key key = Key(15, "clave 15");
	cout << "La clave es : " + Util::intToString(key.obtenerClave()) + "\n";
	;
	cout << "El valor es :" + key.obtenerValor() + "\n";
	cout << "El registro es: ";
	cout << key.obtenerRegistro()->buffer;
	cout << "\n";

}

void leerBloqueTest() {
	ArchivoDeBloques archivo = ArchivoDeBloques("prueba", 20);
	Bloque bloque1 = Bloque(20);

}

void crearBucketTest() {
	Key key1 = Key(15, "cl5");
	Key key2 = Key(16, "cl16");

	Bloque* bloque1 = new Bloque(100);
	Registro registrotd = Registro("444");
	Registro registro1 = *(key1.obtenerRegistro());
	Registro registro2 = *(key2.obtenerRegistro());
	bloque1->agregarRegistro(registrotd);

	cout << "\n PROBANDO CREATE BUCKET!!" << endl;
	Bucket bucket = Bucket(100, bloque1);
	//cout<<"clave: "<< bucket.obtenerClave(registro1.buffer)<<"   valor: "<< bucket.obtenerValor(registro1.buffer)<<endl;
	//cout<<"clave: "<< bucket.obtenerClave(registro2.buffer)<<"   valor: "<< bucket.obtenerValor(registro2.buffer)<<endl;
	cout << "\n Verifico tamanio dispersion: "
			<< bucket.obtenerTamanioDispersion() << endl;
	cout << "\n Verifico bytes libres: " << bucket.obtenerCantidadBytesLibres()
			<< endl;
	cout << "\n Verifico tamanio bucket:" << bucket.vectorKeys.size() << endl;

	cout << "\n PROBANDO INSERT BUCKET!!" << endl;
	Key key3 = Key(17, "cl17");
	Key key4 = Key(18, "cl18");
	bucket.insertar(key1, 8);
	bucket.insertar(key2, 5);
	bucket.insertar(key3, 8);
	bucket.insertar(key4, 5);

	cout << "\n Verifico tamanio bucket:" << bucket.vectorKeys.size() << endl;

	cout << "\n Verifico contenido bucket: " << endl;
	cout << " clave: " << bucket.vectorKeys[0]->obtenerClave() << "  valor: "
			<< bucket.vectorKeys[0]->obtenerValor() << endl;
	cout << " clave: " << bucket.vectorKeys[1]->obtenerClave() << "  valor: "
			<< bucket.vectorKeys[1]->obtenerValor() << endl;
	cout << " clave: " << bucket.vectorKeys[2]->obtenerClave() << "  valor: "
			<< bucket.vectorKeys[2]->obtenerValor() << endl;
	cout << " clave: " << bucket.vectorKeys[3]->obtenerClave() << "  valor: "
			<< bucket.vectorKeys[3]->obtenerValor() << endl;
	cout << "\n Verifico tamanio dispersion: "
			<< bucket.obtenerTamanioDispersion() << endl;
	cout << "\n Verifico bytes libres: " << bucket.obtenerCantidadBytesLibres()
			<< endl;
	cout << "\n Verifico contenido bloque del bucket: "
			<< bucket.obtenerBloque()->bufferBloque << endl;

	if (bucket.existe(key3))
		cout << endl << "Existe 3" << endl;
	else
		cout << endl << "error busqueda no encontro 3" << endl;

	cout << "\n PROBANDO BORRAR DEL BUCKET!!" << endl;
	bucket.borrar(key3, 8);

	cout << "\n Verifico tamanio bucket:" << bucket.vectorKeys.size() << endl;

	cout << "\n Verifico contenido bucket: " << endl;
	cout << " clave: " << bucket.vectorKeys[0]->obtenerClave() << "  valor: "
			<< bucket.vectorKeys[0]->obtenerValor() << endl;
	cout << " clave: " << bucket.vectorKeys[1]->obtenerClave() << "  valor: "
			<< bucket.vectorKeys[1]->obtenerValor() << endl;
	cout << " clave: " << bucket.vectorKeys[2]->obtenerClave() << "  valor: "
			<< bucket.vectorKeys[2]->obtenerValor() << endl;
	cout << "\n Verifico tamanio dispersion: "
			<< bucket.obtenerTamanioDispersion() << endl;
	cout << "\n Verifico bytes libres: " << bucket.obtenerCantidadBytesLibres()
			<< endl;
	cout << "\n Verifico contenido bloque del bucket: "
			<< bucket.obtenerBloque()->bufferBloque << endl;

	if (bucket.existe(key3))
		cout << endl << "error encontro key 3 y estaba borrado" << endl;
	else
		cout << endl << "Todo Ok, no encontro key 3 borrada" << endl;

	cout << "\n PROBANDO MODIFICAR DEL BUCKET!!" << endl;

	Key key6 = Key(18, "modif");
	bucket.modificar(key6, 5);
	Key key7 = Key(200, "c200");
	bucket.insertar(key7, 5);
	Key key8 = Key(200, "modificado");
	bucket.modificar(key8, 5);
	bucket.borrar(key2, 50);

	cout << "\n Verifico tamanio bucket:" << bucket.vectorKeys.size() << endl;

	cout << "\n Verifico contenido bucket: " << endl;
	cout << " clave: " << bucket.vectorKeys[0]->obtenerClave() << "  valor: "
			<< bucket.vectorKeys[0]->obtenerValor() << endl;
	cout << " clave: " << bucket.vectorKeys[1]->obtenerClave() << "  valor: "
			<< bucket.vectorKeys[1]->obtenerValor() << endl;
	cout << " clave: " << bucket.vectorKeys[2]->obtenerClave() << "  valor: "
			<< bucket.vectorKeys[2]->obtenerValor() << endl;

	cout << "\n Verifico contenido bloque del bucket: "
			<< bucket.obtenerBloque()->bufferBloque << endl;

	bloque1->~Bloque();
}

void tablaTDTest() {
	Tabla tabla(6);
	cout << "td" << tabla.obtenertd(2) << endl;
	tabla.modificar(0, 1);
	tabla.modificar(1, 5);
	tabla.modificar(2, 2);
	tabla.modificar(3, 1);
	tabla.modificar(4, 4);
	tabla.modificar(5, 2);
	tabla.mostrar();
	cout << "td" << tabla.obtenertd(2) << endl;
	tabla.duplicarTabla();
	cout << "td" << tabla.obtenertd(2) << endl;
	tabla.reducirTabla();
	cout << "td" << tabla.obtenertd(2) << endl;
	tabla.mostrar();
}

void hashTest() {
	Hash hash = Hash("mihash1", 45);
	Key key1(1, "valor5");
	Key key2(2, "valor2");
	Key key3(8, "clave888888888888");
	Key key4(12, "clave 12");
	Key key5(16, "valor 16");
	Key key6(20, "valor  20");
	Key key7(24, "es el valor 24");

	cout << endl << "**********Empezo prueba insertar**********" << endl
			<< endl;
	cout << "-----Inserta key: " << key1.obtenerClave() << endl;
	hash.insertar(key1);
	hash.mostrar();
	cout << "-----Inserta key: " << key2.obtenerClave() << endl;
	hash.insertar(key2);
	hash.mostrar();
	cout << "-----Inserta key: " << key3.obtenerClave() << endl;
	hash.insertar(key3);
	hash.mostrar();
	cout << "-----Inserta key: " << key4.obtenerClave() << endl;
	hash.insertar(key4);
	hash.mostrar();
	cout << "-----Inserta key: " << key5.obtenerClave() << endl;
	hash.insertar(key5);
	hash.mostrar();
	cout << "-----Inserta key: " << key6.obtenerClave() << endl;
	hash.insertar(key6);
	hash.mostrar();
	cout << "-----Inserta key: " << key7.obtenerClave() << endl;
	hash.insertar(key7);
	hash.mostrar();
	cout << "**********Termino prueba insertar**********" << endl << endl;

	cout << "**********Empezo prueba de existe**********" << endl << endl;
	if (hash.existe(key5)) {
		cout << "OK, encontro elemento existente" << endl;
	} else
		cout << "ERROR,no encontro elemento existente" << endl;

	Key key8(15, "");
	if (hash.existe(key8)) {
		cout << "ERROR, encontro elemento no existente" << endl;
	} else
		cout << "Ok, no encontro elemento no existente" << endl;
	cout << "**********Termino prueba de existe**********" << endl << endl;

	cout << "**********Empezo prueba de buscar**********" << endl << endl;
	cout << "encontro elemento buscado" << hash.buscar(key4) << endl;
	Key key9(16, "la");
	cout << "encontro elemento buscado" << hash.buscar(key9) << endl;
	Key key10(17, "la");
	cout << "no encontro elemento" << hash.buscar(key10) << endl;
	cout << "**********Termino prueba de buscar**********" << endl << endl;

	cout << "**********Empieza la prueba de eliminar**********" << endl << endl;
	cout << "-----Elimina key: " << key6.obtenerClave() << endl;
	hash.eliminar(key6);
	hash.mostrar();
	cout << "-----Elimina key: " << key5.obtenerClave() << endl;
	hash.eliminar(key5);
	hash.mostrar();
	cout << "-----Elimina key: " << key1.obtenerClave() << endl;
	hash.eliminar(key1);
	hash.mostrar();
	cout << "**********Termino prueba eliminar**********" << endl << endl;

	/*cout << "**********Empieza la prueba de nodificar**********" << endl
			<< endl;
	Key key11(12, "esto lo modifique");

	cout << "-----Modifica key: " << key11.obtenerClave() << endl;
	hash.modificar(key11);
	hash.mostrar();
	cout << "-----Modifica key: " << key5.obtenerClave() << endl;
	Key key12(8, "Esto lo modifiqueeee");
	hash.modificar(key12);
	hash.mostrar();
	cout << "-----Modifica key: " << key2.obtenerClave() << endl;
	key2.modificarValor("esto lo modiq tambien");
	hash.modificar(key2);
	hash.mostrar();
	cout << "**********Termino prueba modificar**********" << endl << endl;

	cout << endl
			<< "**********Empezo prueba insertar despues de haber eliminado/modificado**********"
			<< endl << endl;
	cout << "-----Inserta key: " << key1.obtenerClave() << endl;
	hash.insertar(key1);
	hash.mostrar();
	cout << "-----Inserta key: " << key6.obtenerClave() << endl;
	hash.insertar(key6);
	hash.mostrar();
	Key key13(5, "mi valor es el cinco");
	cout << "-----Inserta key: " << key13.obtenerClave() << endl;
	hash.insertar(key13);
	hash.mostrar();
	Key key14(13, "treceeeee");
	cout << "-----Inserta key: " << key14.obtenerClave() << endl;
	hash.insertar(key14);
	hash.mostrar();
	cout << endl
			<< "**********TErmino prueba insertar despues de haber eliminado/modificado**********"
			<< endl << endl;*/

}

void pruebaCantidadBloquesArchivo() {
	Bloque b1 = Bloque(40);
	Bloque b2 = Bloque(40);
	Bloque b3 = Bloque(40);
	Bloque b4 = Bloque(40);
	Bloque b5 = Bloque(40);
	b5.bufferBloque = "lore";
	ArchivoDeBloques archivo = ArchivoDeBloques("pruebacantbloques", 4, 40);
	cout << "Cantidad de bloques: " << archivo.cantBloques << endl;
	archivo.escribirBloque(b1, 0);
	archivo.escribirBloque(b2, 1);
	archivo.escribirBloque(b3, 2);
	archivo.escribirBloque(b4, 3);
	cout << "Cantidad de bloques: aca tendria que dar 4 y da"
			<< archivo.cantBloques << endl;
	archivo.agregarBloquesVacios(1);
	archivo.escribirBloque(b5, 4);
	cout << "Cantidad de bloques: aca tendria que dar 5 y da"
			<< archivo.cantBloques << endl;
	archivo.agregarBloquesVacios(1);
	cout << "Cantidad de bloques: aca tendria que dar 6 y da "
			<< archivo.cantBloques << endl;
	archivo.agregarBloquesVacios(1);
	archivo.escribirBloque(b5, 5);
	cout << "Cantidad de bloques: aca tendria que dar 7 y da"
			<< archivo.cantBloques << endl;

	cout << "Contenido de los bloques del arhivo:" << endl;

	for (unsigned int x = 0; x < archivo.cantBloques; x++) {
		cout << "Bloque: " << x << "  :  "
				<< archivo.leerBloque(x)->bufferBloque << endl;
	}
}

void ABMTest() {


	vector<string> vector;

	/* PRUEBA DE ABMBRETEL */
	cout << endl << " ***** Comienzo de prueba ABMBretel: ***** " << endl;
	ABMBretel abmB = ABMBretel("ArchivoBretel.hash", 35);
	abmB.alta(1, "tipo1");
	abmB.alta(2, "tipo2");
	abmB.alta(3, "tipo3");
	abmB.alta(4, "tipo4");
	abmB.alta(5, "tipo5");
	abmB.alta(6, "tipo6");
	abmB.alta(7, "tipo7");
	abmB.alta(8, "tipo8");
	abmB.modificacion(3, "untipomodificado");
	cout << abmB.buscar(4) << endl;

	vector = abmB.listar(8);
	cout << endl << "Listo el contenido del hash " << "(Tamanio "
			<< vector.size() << ")" << endl;
	for (unsigned int i = 0; i < vector.size(); i++) {
		cout << vector[i] << endl;
	}
	abmB.baja(7);
	abmB.modificacion(8, "tipo8modif");
	vector = abmB.listar(8);
	cout << endl << "Listo el contenido del hash " << "(Tamanio "
			<< vector.size() << ")" << endl;
	for (unsigned int i = 0; i < vector.size(); i++) {
		cout << vector[i] << endl;
	}
	cout << " *** Fin de prueba ABMBretel ***" << endl;

	/* PRUEBA DE ABMFORMADOR*/
	cout << endl << " ***** Comienzo de prueba ABMFormador: ***** " << endl;
	ABMFormador abmF = ABMFormador("ArchivoFormador.hash", 35);
	abmF.alta(1, "tipo1");
	abmF.alta(2, "tipo2");
	abmF.alta(3, "tipo3");
	abmF.alta(4, "tipo4");
	abmF.alta(5, "tipo5");
	abmF.alta(6, "tipo6");
	abmF.alta(7, "tipo7");
	abmF.alta(8, "tipo8");
	abmF.modificacion(3, "tipo3modificado");
	cout << abmF.buscar(4) << endl;

	vector = abmF.listar(8);
	cout << endl << "Listo el contenido del hash " << "(Tamanio "
			<< vector.size() << ")" << endl;
	for (unsigned int i = 0; i < vector.size(); i++) {
		cout << vector[i] << endl;
	}
	abmF.baja(5);
	abmF.modificacion(2, "tipo2modif");
	vector = abmF.listar(8);
	cout << endl << "Listo el contenido del hash " << "(Tamanio "
			<< vector.size() << ")" << endl;
	for (unsigned int i = 0; i < vector.size(); i++) {
		cout << vector[i] << endl;
	}
	cout << " *** Fin de prueba ABMFormador ***" << endl;

	/***ABMMATERIAL***/

	/* PRUEBA DE ABMMATERIAL */
	cout << endl << " ***** Comienzo de prueba ABMMaterial: ***** " << endl;
	ABMMaterial abmM = ABMMaterial("ArchivoMaterial.hash", 35);
	abmM.alta(1, "tela");
	abmM.alta(2, "lana");
	abmM.alta(3, "lentejuelas");
	abmM.alta(4, "jean");
	abmM.alta(5, "elastico");
	abmM.alta(6, "puntilla");
	abmM.alta(7, "cinta");
	abmM.alta(8, "tul");
	abmM.modificacion(3, "lentejuelas verdes");
	cout << abmM.buscar(4) << endl;

	vector = abmM.listar(8);
	cout << endl << "Listo el contenido del hash " << "(Tamanio "
			<< vector.size() << ")" << endl;
	for (unsigned int i = 0; i < vector.size(); i++) {
		cout << vector[i] << endl;
	}
	abmM.baja(1);
	abmM.baja(6);
	abmM.modificacion(8, "tul amarillo");
	vector = abmM.listar(8);
	cout << endl << "Listo el contenido del hash " << "(Tamanio "
			<< vector.size() << ")" << endl;
	for (unsigned int i = 0; i < vector.size(); i++) {
		cout << vector[i] << endl;
	}
	cout << " *** Fin de prueba ABMMaterial ***" << endl;

	/***ABMCOPA***/

	cout << endl << " ***** Comienzo de prueba ABMCopal: ***** " << endl;
	ABMCopa abmC = ABMCopa("ArchivoCopa.hash", 40);
	abmC.alta(1, 1, false, true);
	abmC.alta(2, 3, true, 1);
	abmC.alta(3, 2, true, true);
	abmC.alta(4, 4, false, false);
	abmC.alta(5, 5, true, true);
	abmC.alta(6, 8, false, true);
	abmC.alta(7, 15, 1, 1);
	abmC.alta(8, 2, 0, 1);
	abmC.alta(9, 9, 1, 1);
	abmC.alta(10, 8, 0, 1);
	abmC.alta(11, 5, 1, 1);
	abmC.alta(12, 40, 0, 1);
	abmC.alta(13, 5, 1, 0);
	abmC.alta(14, 2, 0, 1);
	abmC.modificacion(6, 90, 0, 0);
	cout << abmC.buscar(4) << endl;

	vector = abmC.listar(14);
	cout << endl << "Listo el contenido del hash " << "(Tamanio "
			<< vector.size() << ")" << endl;
	for (unsigned int i = 0; i < vector.size(); i++) {
		cout << vector[i] << endl;
	}

	abmC.baja(1);
	abmC.baja(6);
	abmC.baja(10);
	abmC.baja(12);
	abmC.modificacion(8, 60, 0, 0);
	vector = abmC.listar(14);
	cout << endl << "Listo el contenido del hash " << "(Tamanio "
			<< vector.size() << ")" << endl;
	for (unsigned int i = 0; i < vector.size(); i++) {
		cout << vector[i] << endl;
	}
	cout << " *** Fin de prueba ABMCopa ***" << endl;
}

void testIdentificadores() {

	Instancia ids = Instancia();
	cout << "ID Inicial:" << endl;
	cout << ids.obtenerIdBretel() << endl;
	cout << ids.obtenerIdTintura() << endl;
	cout << ids.obtenerIdMaterial() << endl;
	cout << ids.obtenerIdFormador() << endl;
	cout << ids.obtenerIdCopa() << endl;
	cout << ids.obtenerIdVentas() << endl;
	cout << ids.obtenerIdFamilia() << endl;
	cout << ids.obtenerIdCorpinio() << endl;
	cout << "Incremento ID:" << endl;

	ids.incrementarIdBretel();
	ids.incrementarIdCopa();
	ids.incrementarIdCorpinio();
	ids.incrementarIdFamilia();
	ids.incrementarIdFamilia();
	ids.incrementarIdFamilia();
	ids.incrementarIdMaterial();
	ids.incrementarIdMaterial();
	ids.incrementarIdMaterial();
	ids.incrementarIdMaterial();
	ids.incrementarIdMaterial();
	ids.incrementarIdMaterial();
	ids.incrementarIdMaterial();
	ids.incrementarIdMaterial();

	ids.incrementarIdFormador();
	ids.incrementarIdMaterial();
	ids.incrementarIdTintura();
	ids.incrementarIdVentas();
	ids.incrementarIdBretel();

	cout << "ID Final:" << endl;
	cout << ids.obtenerIdBretel() << endl;
	cout << ids.obtenerIdTintura() << endl;
	cout << ids.obtenerIdMaterial() << endl;
	cout << ids.obtenerIdFormador() << endl;
	cout << ids.obtenerIdCopa() << endl;
	cout << ids.obtenerIdVentas() << endl;
	cout << ids.obtenerIdFamilia() << endl;
	cout << ids.obtenerIdCorpinio() << endl;
}

void testReportes(){
    vector<string> vecS=Reporte::splitS("la");
    for(unsigned int i=0;i<vecS.size();i++){
    cout<<i<<" "<<vecS.at(i)<<endl;
    }

    ABMCorpino *abmC=new ABMCorpino("corpino.arbol",35);
    ABMFamilia *abmF=new ABMFamilia("familia.arbol",40);
    ABMVentas *abmV=new ABMVentas("ventas.arbol",45);
    abmF->alta(1,"familiaA","fabricanteA",15);
    abmF->alta(2,"familiaB","fabricanteB",13);
    abmF->alta(3,"familiaC","fabricanteC",55);
    abmF->alta(4,"familiaD","fabricanteD",95);
    abmF->alta(5,"familiaE","fabricanteE",65);

    abmC->alta(1,"corp1",1,344,1,1,1,2,1);
    abmC->alta(2,"corp2",1,443,1,1,1,2,1);
    abmC->alta(3,"corp3",1,533,1,1,1,3,1);
    abmC->alta(4,"corp4",1,354,1,1,1,3,1);
    abmC->alta(5,"corp5",1,344,1,1,1,2,1);
    abmC->alta(6,"corp6",1,334,1,1,1,1,1);
    abmC->alta(7,"corp7",1,343,1,1,1,5,1);
    abmC->alta(8,"corp8",1,348,1,1,1,5,1);

    abmV->alta(3,"mario",1,85,"25112014");
    abmV->alta(1,"pepe",1,85,"25102014");
    abmV->alta(2,"jose",4,85,"25102014");




    Reporte::cantCopiniosPorFamilia(abmC,abmF);
    Reporte::listarCorpiniosPorFamilia(abmC,abmF);
    Reporte::cantCopiniosPorFabricante(abmC,abmF);
    Reporte::listarCorpiniosPorFabricante(abmC,abmF);
    Reporte::listarVentasPorFecha(abmV,abmC);
    Reporte::listadoDeStock(abmV,abmC);
}


int main() {
	cout << "Ingresa a Main" << endl;

//	contarRegistrosTest();
//	escribirRegistroTest();
//	crearBloques();
//	escribirYLeerBloqueTest();
//	crearArchivoTest();
//	agregarRegistroTest();
//	guardarTabla();
//	cargarTabla();
//	metadataTest();
//	obtenerRegistroTest();
//  crearKeyTest();
//  crearBucketTest();
//  tablaTDTest();
//	hashTest();
//	ABMTest();
//  testReportes();
//	pruebaCantidadBloquesArchivo();
//	cargarEntidades();
//	leerEntidades();

//	creacionArbolTest();
//	buscarArbolTest();
//	modificarArbolTest();
//	altaArbolTest();
//	numeroNodoTest();
//ABMTest();
//	verEntidades();
//	testIdentificadores();


	menu();

	cout <<endl<< "Sale de Main" << endl;

	return 0;
}
